
#include "common/person.h"
#include <numeric>
#include <string>
#include <vector>

// common recursion
std::vector<std::string> names_for(std::vector<person_t> people)
{
    if (people.empty()) {
        return {};
    }
    auto head = std::move(people.front());
    people.erase(people.begin());
    auto processed_tail = names_for(std::move(people));
    if (head.gender() == person_t::female) {
        processed_tail.insert(processed_tail.begin(), head.name());
    }
    return processed_tail;
}

// tail recursion
std::vector<std::string>
names_for_tail(std::vector<person_t>::const_iterator beg,
    std::vector<person_t>::const_iterator end,
    std::vector<std::string> pre_names)
{
    if (beg == end) {
        return pre_names;
    }
    if (beg->gender() == person_t::female) {
        pre_names.emplace_back(beg->name());
    }
    return names_for_tail(beg + 1, end, pre_names);
}

std::vector<std::string>
append_name_if(std::vector<std::string> previously_collected,
    const person_t& p)
{
    if (p.gender() == person_t::female) {
        previously_collected.emplace_back(p.name());
    }
    return previously_collected;
}

int main()
{
    std::vector<person_t> people {
        { "David", person_t::male }, { "Jane", person_t::female },
        { "Martha", person_t::female }, { "Peter", person_t::male },
        { "Rose", person_t::female }, { "Tom", person_t::male }
    };
    // auto female_names = names_for(std::move(people));
    // auto female_names = names_for_tail(people.cbegin(), people.cend(), {});
    auto female_names = std::accumulate(
        people.cbegin(), people.cend(), std::vector<std::string> {},
        [](std::vector<std::string> previously_collected, const person_t& p) {
            if (p.gender() == person_t::female) {
                previously_collected.emplace_back(p.name());
            }
            return previously_collected;
        });

    for (auto& item : female_names) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}